package com.suning.park.admin.util.epps;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Maps;
import com.suning.park.admin.bean.Properties;
import com.suning.park.admin.util.DateUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * 支付帮助类
 * Created by Administrator on 2017/1/12.
 */
@Component
public class PaymentHandler {

    private final static Logger logger = LoggerFactory.getLogger(PaymentHandler.class);

    @Autowired
    Properties properties;

    private final static String PAYTIMEOUT = "15m";//支付订单超时时间


    /**
     * 构建支付参数
     *
     * @param paramsMap
     * @return
     */
    public String buildPayParams(Map<String, String> paramsMap) {
        Map<String, String> requestMap = Maps.newHashMap();
        setPublicInfo(requestMap,MapUtils.getString(paramsMap, "merchantNo"));
        requestMap.put("merchantDomain", "");
        requestMap.put("version", "1.1");
        requestMap.put("notifyUrl", properties.getEppsPayNotifyUrl());
        requestMap.put("returnUrl", properties.getEppsPayReturnUrl());
        requestMap.put("buyerIp", "");
        requestMap.put("buyerMerchantLoginName", "");
        requestMap.put("buyerMerchantUserNo", "");
        requestMap.put("creditInstallment", "");
        requestMap.put("appId", "");
        requestMap.put("orders", buildOrders(paramsMap));
        requestMap.put("signature", toSign(requestMap, properties.getEppsMerchantPrivateKey()));//签名产生的换行符去掉
        requestMap.put("requestUrl", properties.getEppsPayUrl());
        return JSON.toJSONString(requestMap, SerializerFeature.DisableCircularReferenceDetect);
//        logger.info("支付参数:{}", buildStrParams(requestMap));
//        StringBuffer formParamters = new StringBuffer();
//        for (Map.Entry<String, String> entry : requestMap.entrySet()) {
//            formParamters.append(buildInputHiddenFieldInForm(entry.getKey(), entry.getValue()));
//        }
//        return buildForm(MapUtils.getString(paramsMap, "requestUrl"), formParamters.toString());
    }


    /**
     * 构建支付订单内容
     *
     * @param map
     * @return
     */
    private String buildOrders(Map<String, String> map) {
        ArrayList<HashMap<String, String>> orderList = new ArrayList<HashMap<String, String>>();
        Map<String, String> order = new HashMap<String, String>();
        order.put("salerUserNo", "");
        order.put("salerMerchantNo", MapUtils.getString(map, "salerMerchantNo"));//卖家易付宝会员编号
        order.put("salerAlias", "");
        order.put("royaltyParameters", "");
        order.put("merchantCode", "");
        order.put("orderType", "01");
        order.put("outOrderNo", MapUtils.getString(map, "orderId"));//支付订单ID
        order.put("merchantOrderNo", MapUtils.getString(map, "orderId"));//支付订单ID
        order.put("goodsName", base64Encode(MapUtils.getString(map, "goodsName")));//商品名称
        order.put("goodsCode", "");
        order.put("goodsType", properties.getEppsGoodsType());//商品类型 由易付宝分配,签署完协议 后给予，参见附录商品类型
        order.put("body", "");
        order.put("showUrl", "");
        order.put("receiveInfo", "");
        order.put("price", "");
        order.put("orderAmount", MapUtils.getString(map, "orderAmount"));//订单金额
        order.put("quantity", "");
        order.put("currency", "CNY");
        order.put("orderTime", MapUtils.getString(map, "orderTime"));//支付订单创建时间
        order.put("payTimeout", PAYTIMEOUT);//支付订单有效期
        order.put("tunnelData", "");
        orderList.add((HashMap<String, String>) order);
        return JSON.toJSONString(orderList, SerializerFeature.DisableCircularReferenceDetect);
    }


    /**
     * 构建订单查询参数
     *
     * @param merchantNo
     * @param orderId
     * @param orderTime
     * @return
     */
    public String buildSelectOrderParams(String merchantNo, String orderId, String orderTime) {
        Map<String, String> requestMap = Maps.newHashMap();
        setPublicInfo(requestMap,merchantNo);
        requestMap.put("outOrderNo", orderId);
        requestMap.put("orderTime", orderTime);
        try {
            requestMap.put("signature", URLEncoder.encode(toSign(requestMap, properties.getEppsMerchantPrivateKey()), "utf-8"));//签名产生的换行符去掉
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return buildStrParams(requestMap);
    }


    /**
     * 构建退款请求参数
     *
     * @param merchantNo
     * @param refundOrderId
     * @param refundOrderTime
     * @param refundAmount
     * @param orderId
     * @param orderTime
     * @return
     * @throws UnsupportedEncodingException
     */
    public String buildRefundOrderParams(String merchantNo, String refundOrderId, String refundOrderTime, String refundAmount, String orderId, String orderTime) {
        Map<String, String> requestMap = Maps.newHashMap();
        setPublicInfo(requestMap,merchantNo);
        requestMap.put("notifyUrl", properties.getEppsPayRefundNotifyUrl());
        requestMap.put("version", "1.1");
        requestMap.put("refundOrderNo", refundOrderId);//退款订单号
        requestMap.put("origMerchantOrderNo", orderId);//正向下单时的原用于展示商 户订单号
        requestMap.put("origOutOrderNo", orderId);//正向下单时的商户网站生成 的唯一订单号
        requestMap.put("origOrderTime", orderTime);//原订单创建时间
        requestMap.put("refundOrderTime", refundOrderTime);
        requestMap.put("refundAmount", refundAmount);//退款金额
        requestMap.put("operator", "");
        requestMap.put("refundReason", "");
        requestMap.put("remark", "");
        requestMap.put("tunnelData", "");
        try {
            requestMap.put("signature", URLEncoder.encode(toSign(requestMap, properties.getEppsMerchantPrivateKey()), "utf-8"));//签名产生的换行符去掉
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return buildStrParams(requestMap);
    }

    /**
     * 构建退款订单查询参数
     *
     * @param merchantNo
     * @param refundOrderNo
     * @param refundOrderTime
     * @return
     */
    public String buildSelectRefundOrderParams(String merchantNo, String refundOrderNo, String refundOrderTime) {
        Map<String, String> requestMap = Maps.newHashMap();
        setPublicInfo(requestMap,merchantNo);
        requestMap.put("refundOrderNo", refundOrderNo);
        requestMap.put("refundOrderTime", refundOrderTime);
        try {
            requestMap.put("signature", URLEncoder.encode(toSign(requestMap, properties.getEppsMerchantPrivateKey()), "utf-8"));//签名产生的换行符去掉
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return buildStrParams(requestMap);
    }

    /**
     * 设置请求公共参数
     * @param requestMap
     * @param merchantNo
     */
    private void setPublicInfo(Map<String, String> requestMap,String merchantNo){
        requestMap.put("merchantNo", merchantNo);//商户号
        requestMap.put("inputCharset", "UTF-8");
        requestMap.put("signAlgorithm", "RSA");
        requestMap.put("publicKeyIndex", properties.getEppsPublicKeyIndex());
        requestMap.put("submitTime", DateUtil.formatDatetimeForYmdhms(new Date()));
    }


    /**
     * 对参数进行签名
     *
     * @param requestMap
     * @param privateKey
     * @return
     */
    private static String toSign(Map<String, String> requestMap, String privateKey) {
        List<String> excudeKeylist = new ArrayList<String>();
        excudeKeylist.add("signature");
        excudeKeylist.add("signAlgorithm");
        logger.info("开始签名");
        String md5Str = SignatureUtil.digest(requestMap, excudeKeylist);
        logger.info("对参数进行排序，然后进行md5加密:{}", md5Str);
        String sign = SignatureUtil.sign(md5Str, privateKey);
        logger.info("对MD5结果进行签名:{}", sign);
        logger.info("requestMap:{}", requestMap);
        return sign.replaceAll("\r\n", "");
    }


    public static String base64Encode(String str) {
        byte[] encodeBase64 = null;
        String result = null;
        if (StringUtils.isEmpty(str)) {
            return str;
        }
        try {
            encodeBase64 = Base64.encodeBase64(str.getBytes("UTF-8"));
            result = new String(encodeBase64, "UTF-8");
        } catch (Throwable e) {
            System.err.println("Base64失败");
        }
        return result;
    }


    /**
     * 测试用
     *
     * @param params
     * @return
     */
    public static String buildStrParams(Map<String, String> params) {
        StringBuilder paramStr = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            paramStr.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        return paramStr.substring(0, paramStr.length() - 1);

    }


    /**
     * 测试用
     *
     * @param paramName
     * @param paramValue
     * @return
     */
    private static String buildInputHiddenFieldInForm(String paramName, String paramValue) {
        String line = "<input type=\"hidden\" name=\"\" value=\"\">";
        if (paramName == null || paramValue == null) {
            return "";
        } else {
            paramValue = paramValue.replaceAll("\"", "&quot;");
            int nameSize = "name=".length() + 1;
            int valueSize = "value=".length() + 1;
            line = line.substring(0, line.indexOf("name=") + nameSize) + paramName
                    + line.substring(line.indexOf("name") + nameSize);
            line = line.substring(0, line.indexOf("value=") + valueSize) + paramValue
                    + line.substring(line.indexOf("value=") + valueSize);
            return line;
        }
    }


    /**
     * 测试用
     * 拼装form表单
     *
     * @return
     */
    private static String buildForm(String url, String inputFiled) {

        StringBuffer form = new StringBuffer();
        form.append("<form name=\"punchout_form\" method=\"post\" action=\"");
        form.append(url);
        form.append("\">");
        form.append(inputFiled);
        form.append("</form>");
        form.append("<input type=\"submit\" value=\"确认\" style=\"display:none;\"></form>");
        //form.append("<script>alert(document.forms[0].orders.value);</script>");
        form.append("<script>document.forms['punchout_form'].submit();</script>");
        return form.toString();
    }
}
